import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;

public class TetrisGame extends JFrame {

    // 定义游戏区域的宽度和高度
    private static final int WIDTH = 10;
    private static final int HEIGHT = 20;
    // 每个方块的大小
    private static final int BLOCK_SIZE = 30;
    // 游戏区域
    private int[][] gameArea = new int[WIDTH][HEIGHT];
    // 当前方块
    private Block currentBlock;
    // 游戏是否结束
    private boolean isGameOver = false;
    // 得分
    private int score = 0;

    public TetrisGame() {
        setTitle("俄罗斯方块");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);
        addKeyListener(new KeyHandler());
        newGame();
        Timer timer = new Timer(300, new GameTimerListener());
        timer.start();
    }

    // 开始新游戏
    private void newGame() {
        for (int i = 0; i < WIDTH; i++) {
            for (int j = 0; j < HEIGHT; j++) {
                gameArea[i][j] = 0;
            }
        }
        isGameOver = false;
        score = 0;
        spawnBlock();
    }

    // 生成新的方块
    private void spawnBlock() {
        Random random = new Random();
        int blockType = random.nextInt(7);
        currentBlock = new Block(blockType);
        if (!isValidPosition(currentBlock)) {
            isGameOver = true;
        }
    }

    // 检查方块位置是否有效
    private boolean isValidPosition(Block block) {
        for (int i = 0; i < block.shape.length; i++) {
            for (int j = 0; j < block.shape[i].length; j++) {
                if (block.shape[i][j] != 0) {
                    int x = block.x + j;
                    int y = block.y + i;
                    if (x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT || gameArea[x][y] != 0) {
                        return false;
                    }
                }
            }
        }
        return true;
    }

    // 移动方块
    private void moveBlock(int dx, int dy) {
        Block newBlock = new Block(currentBlock);
        newBlock.x += dx;
        newBlock.y += dy;
        if (isValidPosition(newBlock)) {
            currentBlock = newBlock;
        }
    }

    // 旋转方块
    private void rotateBlock() {
        Block newBlock = new Block(currentBlock);
        newBlock.rotate();
        if (isValidPosition(newBlock)) {
            currentBlock = newBlock;
        }
    }

    // 消除满行
    private void clearFullLines() {
        int linesCleared = 0;
        for (int y = HEIGHT - 1; y >= 0; y--) {
            boolean isFull = true;
            for (int x = 0; x < WIDTH; x++) {
                if (gameArea[x][y] == 0) {
                    isFull = false;
                    break;
                }
            }
            if (isFull) {
                linesCleared++;
                for (int i = y; i > 0; i--) {
                    for (int x = 0; x < WIDTH; x++) {
                        gameArea[x][i] = gameArea[x][i - 1];
                    }
                }
                for (int x = 0; x < WIDTH; x++) {
                    gameArea[x][0] = 0;
                }
            }
        }
        score += linesCleared * 100;
    }

    // 绘制游戏界面
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        drawGameArea(g);
        drawCurrentBlock(g);
        drawScore(g);
        if (isGameOver) {
            drawGameOver(g);
        }
    }

    // 绘制游戏区域
    private void drawGameArea(Graphics g) {
        for (int i = 0; i < WIDTH; i++) {
            for (int j = 0; j < HEIGHT; j++) {
                if (gameArea[i][j] != 0) {
                    g.setColor(getBlockColor(gameArea[i][j]));
                    g.fillRect(i * BLOCK_SIZE, j * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
                    g.setColor(Color.BLACK);
                    g.drawRect(i * BLOCK_SIZE, j * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
                }
            }
        }
    }

    // 绘制当前方块
    private void drawCurrentBlock(Graphics g) {
        if (currentBlock != null) {
            for (int i = 0; i < currentBlock.shape.length; i++) {
                for (int j = 0; j < currentBlock.shape[i].length; j++) {
                    if (currentBlock.shape[i][j] != 0) {
                        g.setColor(getBlockColor(currentBlock.type));
                        g.fillRect((currentBlock.x + j) * BLOCK_SIZE, (currentBlock.y + i) * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
                        g.setColor(Color.BLACK);
                        g.drawRect((currentBlock.x + j) * BLOCK_SIZE, (currentBlock.y + i) * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
                    }
                }
            }
        }
    }

    // 绘制得分
    private void drawScore(Graphics g) {
        g.setColor(Color.WHITE);
        g.setFont(new Font("Arial", Font.BOLD, 20));
        g.drawString("得分: " + score, WIDTH * BLOCK_SIZE + 20, 50);
    }

    // 绘制游戏结束信息
    private void drawGameOver(Graphics g) {
        g.setColor(Color.RED);
        g.setFont(new Font("Arial", Font.BOLD, 40));
        String message = "游戏结束";
        int x = (WIDTH * BLOCK_SIZE - g.getFontMetrics().stringWidth(message)) / 2;
        int y = HEIGHT * BLOCK_SIZE / 2;
        g.drawString(message, x, y);
    }

    // 获取方块颜色
    private Color getBlockColor(int blockType) {
        switch (blockType) {
            case 1:
                return Color.RED;
            case 2:
                return Color.GREEN;
            case 3:
                return Color.YELLOW;
            case 4:
                return Color.BLUE;
            case 5:
                return Color.CYAN;
            case 6:
                return Color.MAGENTA;
            case 7:
                return Color.ORANGE;
            default:
                return Color.BLACK;
        }
    }

    // 方块类
    private class Block {
        int type;
        int x;
        int y;
        int[][] shape;

        public Block(int type) {
            this.type = type;
            this.x = WIDTH / 2 - 2;
            this.y = 0;
            setShape(type);
        }

        public Block(Block other) {
            this.type = other.type;
            this.x = other.x;
            this.y = other.y;
            this.shape = new int[other.shape.length][];
            for (int i = 0; i < other.shape.length; i++) {
                this.shape[i] = other.shape[i].clone();
            }
        }

        // 设置方块形状
        private void setShape(int type) {
            switch (type) {
                case 1: // I 型方块
                    shape = new int[][]{
                            {1, 1, 1, 1}
                    };
                    break;
                case 2: // J 型方块
                    shape = new int[][]{
                            {0, 1, 0},
                            {0, 1, 0},
                            {1, 1, 0}
                    };
                    break;
                case 3: // L 型方块
                    shape = new int[][]{
                            {0, 1, 0},
                            {0, 1, 0},
                            {0, 1, 1}
                    };
                    break;
                case 4: // O 型方块
                    shape = new int[][]{
                            {1, 1},
                            {1, 1}
                    };
                    break;
                case 5: // S 型方块
                    shape = new int[][]{
                            {0, 1, 1},
                            {1, 1, 0}
                    };
                    break;
                case 6: // T 型方块
                    shape = new int[][]{
                            {0, 1, 0},
                            {1, 1, 1}
                    };
                    break;
                case 7: // Z 型方块
                    shape = new int[][]{
                            {1, 1, 0},
                            {0, 1, 1}
                    };
                    break;
            }
        }

        // 旋转方块
        public void rotate() {
            int[][] rotatedShape = new int[shape[0].length][shape.length];
            for (int i = 0; i < shape.length; i++) {
                for (int j = 0; j < shape[i].length; j++) {
                    rotatedShape[j][shape.length - 1 - i] = shape[i][j];
                }
            }
            shape = rotatedShape;
        }

        public Block move(int i, int i1) {
            return  null;
        }
    }

    // 键盘事件处理
    private class KeyHandler extends KeyAdapter {
        @Override
        public void keyPressed(KeyEvent e) {
            int keyCode = e.getKeyCode();
            if (isGameOver) {
                if (keyCode == KeyEvent.VK_ENTER) {
                    newGame();
                }
            } else {
                switch (keyCode) {
                    case KeyEvent.VK_LEFT:
                        moveBlock(-1, 0);
                        break;
                    case KeyEvent.VK_RIGHT:
                        moveBlock(1, 0);
                        break;
                    case KeyEvent.VK_DOWN:
                        moveBlock(0, 1);
                        break;
                    case KeyEvent.VK_UP:
                        rotateBlock();
                        break;
                    case KeyEvent.VK_SPACE:
                        while (isValidPosition(new Block(currentBlock).move(0, 1))) {
                            moveBlock(0, 1);
                        }
                        break;
                }
                repaint();
            }
        }
    }

    // 游戏定时器监听器
    private class GameTimerListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            if (!isGameOver) {
                moveBlock(0, 1);
                if (!isValidPosition(currentBlock)) {
                    moveBlock(0, -1);
                    lockBlock();
                    clearFullLines();
                    spawnBlock();
                }
                repaint();
            }
        }
    }

    // 锁定方块
    private void lockBlock() {
        for (int i = 0; i < currentBlock.shape.length; i++) {
            for (int j = 0; j < currentBlock.shape[i].length; j++) {
                if (currentBlock.shape[i][j] != 0) {
                    gameArea[currentBlock.x + j][currentBlock.y + i] = currentBlock.type;
                }
            }
        }
    }

    public static void main(String[] args) {
        TetrisGame game = new TetrisGame();
        game.setSize((WIDTH + 3) * BLOCK_SIZE, HEIGHT * BLOCK_SIZE);
        game.setVisible(true);
    }
}